﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using SimpleJson;
using Common;
namespace Dropbox
{
    public partial class DropboxFileSystemItem : BindableBaseCommon
    {
        public DropboxFileSystemItem()
        {
            this.Contents = new ObservableCollection<DropboxFileSystemItem>();
            this.FolderContents = new ObservableCollection<DropboxFileSystemItem>();
            this.FileContents = new ObservableCollection<DropboxFileSystemItem>();

            this.Contents.CollectionChanged += Contents_CollectionChanged;
        }
        ~DropboxFileSystemItem()
        {
            this.Contents.CollectionChanged -= Contents_CollectionChanged;
        }
        
        void Contents_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            switch (e.Action)
            {
                case System.Collections.Specialized.NotifyCollectionChangedAction.Add:
                    foreach (DropboxFileSystemItem item in e.NewItems)
                    {
                        if (!item.IsDirectory)
                            FileContents.Add(item);
                        else
                            FolderContents.Add(item);
                    }
                    break;
#if WINRT
                case System.Collections.Specialized.NotifyCollectionChangedAction.Move:

                    foreach (DropboxFileSystemItem item in e.OldItems)
                    {
                        if (!item.IsDirectory && FileContents.Contains(item) )
                            FileContents.Remove(item);
                        else if (item.IsDirectory && FolderContents.Contains(item))
                            FolderContents.Remove(item);
                    }

                    foreach (DropboxFileSystemItem item in e.NewItems)
                    {
                        if (item.IsDirectory)
                            FileContents.Add(item);
                        else
                            FolderContents.Add(item);
                    }

                    break;
#endif
                case System.Collections.Specialized.NotifyCollectionChangedAction.Remove:
                    foreach (DropboxFileSystemItem item in e.OldItems)
                    {
                        if (!item.IsDirectory && FileContents.Contains(item) )
                            FileContents.Remove(item);
                        else if (item.IsDirectory && FolderContents.Contains(item))
                            FolderContents.Remove(item);
                    }

                    break;
                case System.Collections.Specialized.NotifyCollectionChangedAction.Replace:
                    foreach (DropboxFileSystemItem item in e.OldItems)
                    {
                        if (!item.IsDirectory && FileContents.Contains(item) )
                            FileContents.Remove(item);
                        else if (item.IsDirectory && FolderContents.Contains(item))
                            FolderContents.Remove(item);
                    }

                    foreach (DropboxFileSystemItem item in e.NewItems)
                    {
                        if (item.IsDirectory)
                            FileContents.Add(item);
                        else
                            FolderContents.Add(item);
                    }

                    break;
                case System.Collections.Specialized.NotifyCollectionChangedAction.Reset:
                    FolderContents.Clear();
                    FileContents.Clear();
                    break;
                default:
                    break;
            }
        }
        protected string originalString = "";
        public String ToJSON()
        {
            if (!String.IsNullOrEmpty(originalString))
                return originalString;
            // TODO: Produce JSON from object 

            return SimpleJson.SimpleJson.SerializeObject(this); // this probably won't work..
        }
        
        public static DropboxFileSystemItem Load(string json)
        {
            var result = new DropboxFileSystemItem();
            JsonObject jsonObj;
            result.originalString = json;
            try
            {

                jsonObj = (JsonObject)SimpleJson.SimpleJson.DeserializeObject(json);
            }
            catch (Exception ex)
            {
                return result;
            }
            if (jsonObj.ContainsKey("size"))
            {
                result.SizeString = jsonObj["size"].ToString();
            }
            if (jsonObj.ContainsKey("hash"))
            {
                result.Hash = jsonObj["hash"].ToString();
            }
            if (jsonObj.ContainsKey("bytes"))
            {
                result.SizeInBytes = (long)jsonObj["bytes"];
            }
            if (jsonObj.ContainsKey("thumb_exists"))
            {
                result.ThumbExists = (bool)jsonObj["thumb_exists"];
            }
            if (jsonObj.ContainsKey("rev"))
            {
                result.Revision = jsonObj["rev"].ToString();
            }
            if (jsonObj.ContainsKey("modified"))
            {
                result.LastModifiedString = jsonObj["modified"].ToString();
                DateTime date;
                if (DateTime.TryParse(result.LastModifiedString, out date))
                    result.LastModified = date;
            }
            if (jsonObj.ContainsKey("path"))
            {
                result.Path = jsonObj["path"].ToString();
            }
            if (jsonObj.ContainsKey("is_dir"))
            {
                result.IsDirectory = (bool)jsonObj["is_dir"];
            }
            if (jsonObj.ContainsKey("icon"))
            {
                result.Icon = jsonObj["icon"].ToString();
            }
            if (jsonObj.ContainsKey("root"))
            {
                result.Root = jsonObj["root"].ToString();
            }
            if (jsonObj.ContainsKey("mime_type"))
            {
                result.MimeType = jsonObj["mime_type"].ToString();
            }
            if (jsonObj.ContainsKey("contents"))
            {
                var jsonArray = (JsonArray)jsonObj["contents"];
                if (jsonArray.Count > 0)
                {
                    result.Contents.Clear();
                    foreach(var i in jsonArray)
                    {
                        result.Contents.Add(DropboxFileSystemItem.Load(i.ToString()));
                    }
                }
            }
            return result;
        }

        private string _SizeString = string.Empty;
        public string SizeString
        {
            get { return this._SizeString; }
            set { this.SetProperty(ref this._SizeString, value
#if !WINRT
, "SizeString"
#endif
                ); }
        }

        private string _Hash = string.Empty;
        public string Hash
        {
            get { return this._Hash; }
            set
            {
                this.SetProperty(ref this._Hash, value
#if !WINRT
, "Hash"
#endif
);
            }
        }

        private long _SizeInBytes = 0;
        public long SizeInBytes
        {
            get { return this._SizeInBytes; }
            set { 
                this.SetProperty(ref this._SizeInBytes, value
#if !WINRT
, "SizeInBytes"
#endif
);
                if (!IsDirectory)
                    SubTitle = "";
                }
        }

        private bool _ThumbExists = false;
        public bool ThumbExists
        {
            get { return this._ThumbExists; }
            set { this.SetProperty(ref this._ThumbExists, value
#if !WINRT
, "ThumbExists"
#endif
); }
        }

        private string _Revision = string.Empty;
        public string Revision
        {
            get { return this._Revision; }
            set { this.SetProperty(ref this._Revision, value
#if !WINRT
, "Revision"
#endif                
                ); }
        }

        private string _LastModifiedString = string.Empty;
        public string LastModifiedString 
        {
            get { return this._LastModifiedString; }
            set
            {
                this.SetProperty(ref this._LastModifiedString, value
#if !WINRT
, "LastModifiedString"
#endif                
                ); }
        }

        private DateTime _LastModified = DateTime.MinValue;
        public DateTime LastModified
        {
            get { return this._LastModified; }
            set
            {
                this.SetProperty(ref this._LastModified, value
#if !WINRT
, "LastModified"
#endif               
                ); }
        }

        private string _Path = string.Empty;
        public string Path
        {
            get { return this._Path; }
            set { 
                this.SetProperty(ref this._Path, value
#if !WINRT
, "Path"
#endif               
                    );
                Name = value;
                FileName = value;
                if (IsDirectory)
                    SubTitle = "";
                Parent = value;
            }
        }

        private bool _IsDirectory = true;
        public bool IsDirectory
        {
            get { return this._IsDirectory; }
            set { 
                this.SetProperty(ref this._IsDirectory, value
#if !WINRT
, "IsDirectory"
#endif               
                    ); 
                SubTitle = ""; }
        }

        private string _Icon = string.Empty;
        public string Icon
        {
            get { return this._Icon; }
            set { this.SetProperty(ref this._Icon, value
#if !WINRT
, "Icon"
#endif               
                ); 
                Image = value; }
        }

        private string _Root = string.Empty;
        public string Root
        {
            get { return this._Root; }
            set
            {
                this.SetProperty(ref this._Root, value
#if !WINRT
, "Root"
#endif 
                ); }
        }

        private string _MimeType = string.Empty;
        public string MimeType
        {
            get { return this._MimeType; }
            set
            {
                this.SetProperty(ref this._MimeType, value
#if !WINRT
, "MimeType"
#endif 
                ); }
        }

        public ObservableCollection<DropboxFileSystemItem> Contents { get; private set; }

        #region Calculated fields

        public ObservableCollection<DropboxFileSystemItem> FolderContents { get; private set; }

        public ObservableCollection<DropboxFileSystemItem> FileContents { get; private set; }

        private string _name;
        public string Name
        {
            get
            {
                return _name;
            }
            set
            {
                var calcValue = System.IO.Path.GetFileNameWithoutExtension(value.Replace("/", @"\").Trim('\\'));

                this.SetProperty(ref this._name, calcValue
#if !WINRT
, "Name"
#endif 
                    );
            }
        }

        private string _fileName;
        public string FileName
        {
            get
            {
                return _fileName;
            }
            set
            {
                var calcValue = System.IO.Path.GetFileName(value.Replace("/", @"\").Trim('\\'));

                this.SetProperty(ref this._fileName, calcValue
#if !WINRT
, "FileName"
#endif 
                    );
            }
        }

        String _Image;
        public String Image
        {
            get
            {
                return _Image;
            }
            set
            {
                var calcValue = String.Format("Assets/Dropbox/{0}{1}", Icon, !Icon.Contains(".") ? ".gif" : "");

                this.SetProperty(ref this._Image, calcValue
                    
#if !WINRT
, "Image"
#endif 
);
            }
        }

        String _Parent;
        public string Parent
        {
            get { return _Parent; }
            set
            {
                var newValue = "";
                var val2 = Path.Split('/');
                if (val2.Length > 2)
                    newValue = String.Join("/", val2.Take(val2.Length - 1).ToArray());
                else
                    newValue = "";

                this.SetProperty(ref this._Parent, newValue
                    
#if !WINRT
, "Parent"
#endif 
);
            }
        }
        
        String _SubTitle;
        public string SubTitle
        {
            get { return _SubTitle; }
            set
            {
                var newValue = "";
                if (IsDirectory)
                {
                    var val2 = Path.Split('/');
                    if (val2.Length > 2)
                        newValue = "parent: " + String.Join("/", val2.Take(val2.Length - 1).ToArray());
                    else
                        newValue = "parent: (root)";
                }
                else
                    newValue = SizeString;
                this.SetProperty(ref this._SubTitle, newValue
                    
#if !WINRT
, "SubTitle"
#endif 
);
            }
        }
        #endregion

        internal static DropboxFileSystemItem NewItem(string path)
        {
            return new DropboxFileSystemItem
            {
                Path = path,
                Parent = System.IO.Path.GetDirectoryName(path.Replace("/", @"\")).Replace(@"\", "/"),
                SizeInBytes = 0,
                Root = "dropbox"
            };
        }
    }
}
